package com.etung.iot.demo.websocket;
import java.util.List;
import	java.util.concurrent.ConcurrentHashMap;

import com.etung.iot.demo.constant.WebSocketConstant;
import com.etung.iot.demo.services.UserService;
import com.google.common.collect.Lists;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.yeauty.annotation.*;
import org.yeauty.pojo.Session;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

@ServerEndpoint(path = "/ws/test", host = "${ws.host}",port = "${ws.port}")
@Slf4j
public class MyWebSocket {
    public static Map<String, CopyOnWriteArrayList<Session>> sessionMap = new ConcurrentHashMap<String, CopyOnWriteArrayList<Session>> ();

    @Autowired
    private UserService userService;

    @BeforeHandshake
    public void handshake(Session session, HttpHeaders headers, @RequestParam String token, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
        log.info("token:" + token);
        if(StringUtils.isEmpty(token)){
            log.error("认证失败！");
            session.close();
        }else{
            String userId = userService.retrieveUserIdFromToken(token);
            session.setAttribute("USERID",userId);
            if (sessionMap.containsKey(userId)){
                sessionMap.get(userId).add(session);
            }else{
                CopyOnWriteArrayList<Session> sessionList = Lists.newCopyOnWriteArrayList();
                sessionList.add(session);
                sessionMap.put(userId,sessionList);
            }
        }

    }

    @OnOpen
    public void onOpen(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
        System.out.println("new connection");
        System.out.println(req);
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        System.out.println("one connection closed");
        String userId = session.getAttribute("USERID");
        if (!StringUtils.isEmpty(userId) && sessionMap.containsKey(userId)){
            sessionMap.get(userId).remove(session);
        }
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        throwable.printStackTrace();
    }

    @OnMessage
    public void onMessage(Session session, String message) {
        System.out.println(message);
        session.sendText("Hello Netty!你好");
    }

    @OnBinary
    public void onBinary(Session session, byte[] bytes) {
        for (byte b : bytes) {
            System.out.println(b);
        }
        session.sendBinary(bytes);
    }

    @OnEvent
    public void onEvent(Session session, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            switch (idleStateEvent.state()) {
                case READER_IDLE:
                    System.out.println("read idle");
                    break;
                case WRITER_IDLE:
                    System.out.println("write idle");
                    break;
                case ALL_IDLE:
                    System.out.println("all idle");
                    break;
                default:
                    break;
            }
        }
    }

    public void pushRealData(String userId,String message){
        log.info("send message:" + message);
        if(sessionMap.containsKey(userId)){
            sessionMap.get(userId).forEach(session -> {
                session.sendText(message);
            });
        }else if(WebSocketConstant.BROADCAST.equals(userId)){
            sessionMap.forEach((userIdentify,sessionList)->{
                sessionList.forEach(session -> {
                    session.sendText(message);
                });
            });
        }
    }

}